// License Notification
//======================================================
// Copyright (c) 2010 Channel Intelligence Inc.
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// which accompanies this distribution, and is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// ======================================================




using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace CIP4.RulesEngine
{
    public class PathEvaluatorType
    {
        List<PathElementType> PathElements = new List<PathElementType>();

        public string Path { get; private set; }

        public PathEvaluatorType(string aPath)
        {
            Path = aPath;
            string[] parts = Path.Split(new char[] { '.' });
            for( int index = 1; index < parts.Length; index++)
            {
                string part = parts[index];
                PathElements.Add(new PathElementType(part));
            }
        }

        public IEnumerable<object> GetValues(object forValue)
        {
            if (PathElements.Count > 0)
                foreach (object value in GetValues(forValue, 0))
                    yield return value;
            yield break;
        }

        IEnumerable<object> GetValues(object forValue, int pathElementIndex)
        {
            foreach (object value in PathElements[pathElementIndex].GetValues(forValue))
            {
                if (pathElementIndex == PathElements.Count - 1)
                    yield return value;
                else
                    foreach (object subValue in GetValues(value, pathElementIndex + 1))
                        yield return subValue;
            }
        }

        private class PathElementType
        {
            private PropertyInfo _Prop;
            
            public string Name { get; set; }
            
            public PathElementType(string aName)
            {
                Name = aName;
            }

            public IEnumerable<object> GetValues(object forValue)
            {
                if (_Prop == null)
                    _Prop = forValue.GetType().GetProperty(Name);
                if (_Prop == null)
                    yield break;
                object value = _Prop.GetValue(forValue, new object[] {});
                if (value is IList)
                    foreach (object valueObject in ((IList)value))
                        yield return valueObject;
                else if (value != null)
                    yield return value;
                else
                    yield break;
            }

        }
    }
}
